package cn.stevenyang.tests;

import cn.stevenyang.BasicInterpreter;
import cn.stevenyang.exceptions.VariableNotFoundException;
import cn.stevenyang.exceptions.VariablePathTooDeepException;
import cn.stevenyang.gen.BasicParserLexer;
import cn.stevenyang.gen.BasicParserParser;
import cn.stevenyang.services.MemoryService;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class MemoryServiceTest {
    @Test
    public void writeMemoryTest() throws VariablePathTooDeepException, VariableNotFoundException {
        MemoryService memoryService = new MemoryService();
        memoryService.setVariable("test", 5);
        memoryService.setVariable("test1.test2", 2);
        memoryService.setVariable("test2.test3.test4", 1);
        memoryService.setVariable("test3.test4.test5.test6", 12);
        memoryService.setVariable("test31.test4.test5.test6.test7", 10);
        memoryService.setVariable("test3.test4.test5.test5", 7);
        Assertions.assertEquals(5, (int) memoryService.getVariable("test"));
        Assertions.assertEquals(2, (int) memoryService.getVariable("test1.test2"));
        Assertions.assertEquals(1, (int) memoryService.getVariable("test2.test3.test4"));
        Assertions.assertEquals(12, (int) memoryService.getVariable("test3.test4.test5.test6"));
        Assertions.assertEquals(10, (int) memoryService.getVariable("test31.test4.test5.test6.test7"));
        Assertions.assertEquals(7, (int) memoryService.getVariable("test3.test4.test5.test5"));
        memoryService.setVariable("test3.test4.test5.test6", 8);
        Assertions.assertEquals(8, (int) memoryService.getVariable("test3.test4.test5.test6"));
        Assertions.assertEquals(true, memoryService.hasDefinedVariable("test31.test4.test5.test6.test7"));
        Assertions.assertEquals(true, memoryService.hasDefinedVariable("test31.test4.test5.test6"));
        Assertions.assertEquals(false, memoryService.hasDefinedVariable("test3.test41.test5.test6"));
        Assertions.assertEquals(false, memoryService.hasDefinedVariable("test3.test4.test5.test61"));
        Assertions.assertEquals(false, memoryService.hasDefinedVariable("test3.test4.test51.test6"));
        memoryService.setVariable("may", 5);
        memoryService.setVariable("may", 6);
        memoryService.setVariable("may", 7);
        Assertions.assertEquals(7, memoryService.getVariable("may"));
        memoryService.setVariable("may1.may", 8);
        memoryService.setVariable("may1.may", 9);
        Assertions.assertEquals(9, memoryService.getVariable("may1.may"));
    }

    @Test
    public void codeDefineVarTest() throws VariableNotFoundException, VariablePathTooDeepException {
        BasicInterpreter interpreter = runCode("Dim test As Integer = 12");
        Assertions.assertEquals(12, interpreter.getCallStackService().getVariableOrNull("test"));
    }

    public BasicInterpreter runCode(String code) {
        BasicParserLexer lexer = new BasicParserLexer(CharStreams.fromString(code));
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        BasicParserParser parser = new BasicParserParser(tokenStream);

        BasicParserParser.ProcessContext tree = parser.process();
        BasicInterpreter interpreter = new BasicInterpreter();
        interpreter.visit(tree);
        return interpreter;
    }
}

